import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.io.Serializable;

import mobilefeel.AndroidDevice;
import mobilefeel.DeviceListener;
import mobilefeel.MobileFeel;
import mobilefeel.accelerometer.AccelerometerListener;
import mobilefeel.dto.AccelerometerEvent;
import mobilefeel.dto.TouchEvent;
import mobilefeel.touchscreen.OnTouchListener;
import mobilefeel.touchscreen.View;
import mobilefeel.touchscreen.ViewListener;



public class StreetView implements DeviceListener, AccelerometerListener, ViewListener, OnTouchListener {

	private MobileFeel android;
	private Robot robot;
	private boolean step = false;
	private int stepN = 0;
	private float startX = 0F;
	private float startY = 9.81F;
	private float startZ = 0F;
	private float lastX = 0F;
	private float lastY = 9.81F;
	private float lastZ = 0F;
	private float screenDownX;
	private float screenDownY;
	private float screenDownX2;
	private float screenDownY2;
	private double screenDistanceDown;
	private VistaStreetView vista;
	
	/*public static void main(String[] args) {
		new StreetView();
	}*/
	
	public StreetView(VistaStreetView v) {
		try {
			robot = new Robot();
		} catch (AWTException e1) {
			e1.printStackTrace();
		}
		vista = v;
		
		android =  new MobileFeel();
		android.addDeviceListener(this);
	}
	
	public void listen(int port) {
		try {
			android.listen(port);
			vista.update("Escuchando en puerto " + port + "...");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void onDeviceConnected(AndroidDevice device) {
		//System.out.println("DEVICE: " + device.getModel());
		vista.update("Dispositivo conectado: " + device.getModel());
		device.getTouchScreen().addViewListener(this);
	}

	@Override
	public void onDeviceDisconnected(AndroidDevice device) {
		vista.update("Dispositivo desconectado: " + device.getModel());
	}

	@Override
	public void onCustomDataReceived(AndroidDevice device, String text,
			Serializable object) {
	}

	@Override
	public void onSensorChanged(AndroidDevice device, AccelerometerEvent event) {
		lastX = event.getX();
		lastY = event.getY();
		lastZ = event.getZ();

		isStep(device, event);
	}
	
	public boolean isStep(AndroidDevice device, AccelerometerEvent event) {
		if (((Math.abs(startX) + Math.abs(event.getX()) < 2)) && 
				((Math.abs(startY) - Math.abs(event.getY())) > 0) &&
				(event.getZ() > (startZ + 3))) {
			if (!step)
				step = true;
		} else if (((Math.abs(startX) + Math.abs(event.getX()) < 2)) && 
				((Math.abs(startY) - Math.abs(event.getY())) < 0) &&
				(event.getZ() < (startZ + 3))) {
			if (step) {
				step = false;
				stepN++;
				System.out.println("STEP " + stepN);
				pressKey(KeyEvent.VK_UP);
				return true;
			}
		}
		return false;
	}
	
	public void pressKey(final int key) {
		robot.keyPress(key);
		robot.delay(100);
		robot.keyRelease(key);
	}
	
	@Override
	public void onViewRegistered(AndroidDevice device, View view) {
		if(view.getName().equals("Street View")){
			try {
				vista.update("Recibiendo movimientos...");
				device.getAccelerometer().addAccelerometerListener(this);
				view.addOnTouchListener(this);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public void calibrate() {
		startX = lastX;
		startY = lastY;
		startZ = lastZ;
		//System.out.println("Calibrated to: " + startX + "; " + startY + "; " + startZ);
		vista.update("Calibrado a: " + startX + "; " + startY + "; " + startZ);
	}
	
	public void resetCalibration() {
		startX = 0F;
		startY = 9.81F;
		startZ = 0F;
		vista.update("Calibrado a: " + startX + "; " + startY + "; " + startZ);
	}
	
	@Override
	public void onTouch(View v, TouchEvent e) {
		if(v.getName().equals("Street View")){
			if (e.getAction() == TouchEvent.ACTION_DOWN) {
				screenDownX = e.getCurrentByIndex(0).getX();
				screenDownY = e.getCurrentByIndex(0).getY();
			} else if (e.getAction() == TouchEvent.ACTION_POINTER_DOWN) {
				screenDownX = e.getCurrentByIndex(0).getX();
				screenDownY = e.getCurrentByIndex(0).getY();
				screenDownX2 = e.getCurrentByIndex(1).getX();
				screenDownY2 = e.getCurrentByIndex(1).getY();
				screenDistanceDown = Math.sqrt(Math.pow((screenDownX - screenDownX2), 2) + Math.pow((screenDownY - screenDownY2), 2));
			} else if (e.getAction() == TouchEvent.ACTION_MOVE) {
				float screenUpX = e.getCurrentByIndex(0).getX();
				float screenUpY = e.getCurrentByIndex(0).getY();
				if (e.getPointerCount() == 1) {
					//Rotación
					if (screenUpX > screenDownX + 30)
						pressKey(KeyEvent.VK_LEFT);
					else if (screenUpX < screenDownX - 30)
						pressKey(KeyEvent.VK_RIGHT);
					
					//Mirar arriba/mirar abajo
					if (screenUpY < screenDownY - 50)
						pressKey(KeyEvent.VK_PAGE_UP);
					else if (screenUpY > screenDownY + 50)
						pressKey(KeyEvent.VK_PAGE_DOWN);
				} else {
					//Pinch Zoom
					float screenUpX2 = e.getCurrentByIndex(1).getX();
					float screenUpY2 = e.getCurrentByIndex(1).getY();
					double screenDistanceUp = Math.sqrt(Math.pow((screenUpX - screenUpX2), 2) + Math.pow((screenUpY - screenUpY2), 2));
					if (screenDistanceUp > screenDistanceDown + 120)
						pressKey(KeyEvent.VK_PLUS);
					else if (screenDistanceUp < screenDistanceDown - 120)
						pressKey(KeyEvent.VK_MINUS);
					screenDownX2 = screenUpX2;
					screenDownY2 = screenUpY2;
				}
				screenDownX = screenUpX;
				screenDownY = screenUpY;
			}
		}
		
	}

	public void stop() {
		try {
			android.stopListening();
		} catch (IOException e) {
			e.printStackTrace();
		}
		vista.update("Cerrando servidor...");
	}

}
